<?php

namespace App\Console\Commands;

use App\Models\DownloadTasks;
use Illuminate\Console\Command;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Exception;
class ProcessDownloadTasks extends Command
{
    // 命令名称和描述（定时任务将调用此名称）
    protected $signature = 'download:process';
    protected $description = '处理下载任务：每次下载3个未完成的文件';

    public function handle()
    {
        // 1. 查询3个未完成的任务（按创建时间正序，先创建的先下载）
        $tasks = DownloadTasks::query()->where('is_complate', 0)
            ->orderBy('created_at', 'asc')
            ->limit(3)
            ->get();
        if ($tasks->isEmpty()) {
            $this->info('没有待处理的下载任务');
            return Command::SUCCESS;
        }

        $this->info("开始处理 {$tasks->count()} 个下载任务...");

        // 2. 逐个处理任务
        foreach ($tasks as $task) {
            try {
                $this->info("开始下载：{$task->download_url}");

                // 解析URL，构建本地存储路径（保持远程目录结构）
                $parsedUrl = parse_url($task->download_url);
                $remotePath = ltrim($parsedUrl['path'], '/'); // 远程路径（如 static/uploads/fileXml/GD2402.xml）

                // 本地基础目录（可根据项目ID或源表名区分）
                $localBaseDir = storage_path("app/downloads");
                $localFilePath = "{$localBaseDir}/{$remotePath}";

                // 创建本地目录（自动创建多级目录）
                $localDir = dirname($localFilePath);
                if (!file_exists($localDir)) {
                    mkdir($localDir, 0755, true);
                }

                // 流方式下载大文件（避免内存溢出）
                $streamContext = stream_context_create([
                    'http' => [
                        'timeout' => 300, // 超时时间5分钟
                        'user_agent' => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'
                    ],
                    'ssl' => [
                        'verify_peer' => false, // 本地测试可关闭SSL验证
                        'verify_peer_name' => false
                    ]
                ]);

                $remoteStream = fopen($task->download_url, 'r', false, $streamContext);
                if (!$remoteStream) {
                    throw new Exception('无法连接到远程文件');
                }

                $localStream = fopen($localFilePath, 'w');
                if (!$localStream) {
                    fclose($remoteStream);
                    throw new Exception('无法创建本地文件');
                }
                // 分块写入（每次1MB）
                while (!feof($remoteStream)) {
                    fwrite($localStream, fread($remoteStream, 1048576));
                }
                // 关闭流
                fclose($localStream);
                fclose($remoteStream);
                // 验证文件是否下载成功
                if (!file_exists($localFilePath) || filesize($localFilePath) === 0) {
                    throw new Exception('文件下载后为空或不存在');
                }
                // 下载成功：更新任务状态
                $task->update([
                    'is_complate' => 1,
                    'complate_time' => Carbon::now()
                ]);
                $this->info("下载成功：{$task->download_url}");

            } catch (Exception $e) {
                // 下载失败：记录错误（不更新状态，下次继续尝试）
                $this->error("下载失败【{$task->id}】：{$e->getMessage()}");
                // 可选：记录到日志
                Log::error("下载任务失败", [
                    'task_id' => $task->id,
                    'url' => $task->download_url,
                    'error' => $e->getMessage()
                ]);
            }
        }

        $this->info("本次任务处理完成");
        return Command::SUCCESS;
    }
}
